/**
 * 设计二、三中的server
*/
#include "serverutils.h"

//当前工作目录
vector<folderiNode> workpath;
//用户输入的指令及参数
vector<string> cmdv;
//用户id，默认-1表示空
int userid = -1;
//是否第一次循环
bool firsttime = true;
//tid
pthread_t threads[16];
//参数，用于传递给线程使用
shared_mem_st arg[16];

/**
 * 主函数，程序入口
*/
int main(int argc, char *argv[])
{
    string cmdstr, line, pathstr;
    //初始化共享内存
    void *shm = NULL;
    int shmid;
    struct shared_mem_st *shared = NULL;
    //创建共享内存
    shmid = shmget((key_t)MEMKEY, sizeof(struct shared_mem_st), 0666 | IPC_CREAT);
    if (shmid == -1)
    {
        fprintf(stderr, "shmget failed\n");
        exit(EXIT_FAILURE);
    }
    //将共享内存连接到当前进程的地址空间
    shm = shmat(shmid, (void *)0, 0);
    if (shm == (void *)-1)
    {
        fprintf(stderr, "shmat failed\n");
        exit(EXIT_FAILURE);
    }
    printf("Memory attached at 0x%X\n", (long int)shm);
    //共享内存映射到变量
    shared = (struct shared_mem_st *)shm;
    //初始化信号量
    pthread_mutex_init(&wmutex, 0);
    pthread_mutex_init(&rcmutex, 0);
    pthread_mutex_init(&rwmutex, 0);
    //开始接收
    shared->userid = -1;

    while (1)
    {
        //等待shell发送请求
        if (shared->userid >= REPLYSIGN || shared->userid < 0)
        {
            sleepms(500);
            continue;
        }
        //读取共享内存信息
        line = shared->cmd;
        pathstr = shared->workpath;
        userid = shared->userid;
        //解除占用
        shared->userid = -1;
        string output;
        //获取工作目录向量
        getFolderByPath(workpath, pathstr, output);
        loadBitMap();
        //清空命令向量
        cmdv.clear();
        //分割整行命令
        SplitString(line, cmdv, " ");
        cmdstr = cmdv[0];
        //判断命令并执行
        if (!cmdstr.compare("info"))
        {
            DiskStatus ds = getDiskStatus();
            strcpy(shared->output, ds.toString().c_str());
            strcpy(shared->workpath, getStringPath(workpath).c_str());
            shared->userid = userid + REPLYSIGN;
        }
        else if (!cmdstr.compare("shutdown"))
        {
            cout << "shutdown by id." << userid << endl;
            //把共享内存从当前进程中分离
            if (shmdt(shm) == -1)
            {
                fprintf(stderr, "shmdt failed\n");
                exit(EXIT_FAILURE);
            }
            //删除共享内存
            if (shmctl(shmid, IPC_RMID, 0) == -1)
            {
                fprintf(stderr, "shmctl(IPC_RMID) failed\n");
                exit(EXIT_FAILURE);
            }
            exit(0);
        }
        else if (isWriteOp(cmdstr)) //read operate
        {
            //执行写者操作
            arg[userid].userid = userid;
            strcpy(arg[userid].cmd, line.c_str());
            strcpy(arg[userid].workpath,pathstr.c_str());
            pthread_create(&(threads[userid]), NULL, writer, &arg[userid]);
        }
        else if(isReadOp(cmdstr)){
            //执行读者操作
            arg[userid].userid = userid;
            strcpy(arg[userid].cmd, line.c_str());
            strcpy(arg[userid].workpath,pathstr.c_str());
            pthread_create(&(threads[userid]), NULL, reader, &arg[userid]);
        }
        else
        {
            strcpy(shared->output, "command error! try again.\n");
            strcpy(shared->workpath, getStringPath(workpath).c_str());
            shared->userid = userid + REPLYSIGN;
        }
        sleepms(500);
    }
    //把共享内存从当前进程中分离
    if (shmdt(shm) == -1)
    {
        fprintf(stderr, "shmdt failed\n");
        exit(EXIT_FAILURE);
    }
    //删除共享内存
    if (shmctl(shmid, IPC_RMID, 0) == -1)
    {
        fprintf(stderr, "shmctl(IPC_RMID) failed\n");
        exit(EXIT_FAILURE);
    }
    exit(0);
}